﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Daemon.Repository.EF.Executor
{
	public static class SESUtil
	{
		/// <summary>
		/// Load config from web.config only first time use.
		/// </summary>
		private static readonly SesEmailConfig _clientConfig = GetEmailConfig("SesEmail");

		private static readonly SesEmailConfig _clientBillingConfig = GetEmailConfig("SesBillingEmail");

		/// <summary>
		/// Send email with AWS SES
		/// </summary>
		/// <param name="emailAddress">email Address</param>
		/// <param name="subject">email subject</param>
		/// <param name="body">email body</param>
		/// <param name="isHtml">email body is html</param>
		/// <param name="clientKey">client key</param>
		/// <param name="attachments">email attachments</param>
		/// <returns>send success or error</returns>
		public static bool SendEmail(string emailAddress, string subject, string body, bool isHtml, string clientKey, List<Attachment> attachments = null)
		{
			try
			{
				using (MailMessage mailMessage = new MailMessage())
				{
					mailMessage.To.Add(emailAddress);
					mailMessage.Subject = subject;
					mailMessage.IsBodyHtml = isHtml;
					mailMessage.From = new MailAddress(_clientConfig.FromEmailAddress, _clientConfig.FromName);
					mailMessage.Body = body;
					if (attachments != null)
					{
						for (int i = 0; i < attachments.Count; i++)
						{
							mailMessage.Attachments.Add(attachments[i]);
						}
					}

					using (SmtpClient client = new SmtpClient
					{
						DeliveryMethod = SmtpDeliveryMethod.Network,
						EnableSsl = _clientConfig.SMTPSSL,
						Host = _clientConfig.SMTPHost,
						Port = _clientConfig.SMTPPort,
						UseDefaultCredentials = false,
						Credentials = new NetworkCredential(_clientConfig.Username, _clientConfig.Password),
						Timeout = 10000,
					})
					{
						client.Send(mailMessage);
					}
				}

				return true;
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
				return false;
			}
		}

		private static AlternateView ContentToAlternateView(string content)
		{
			Stream Base64ToImageStream(string base64String)
			{
				byte[] imageBytes = Convert.FromBase64String(base64String);
				MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
				return ms;
			}

			var imgCount = 0;
			List<LinkedResource> resourceCollection = new List<LinkedResource>();
			foreach (Match m in Regex.Matches(content, @"<img([\s\S]+?)src\s?=\s?['""](?<srcAttr>[^'""]+?)['""]([\s\S]+?)\/?>"))
			{
				imgCount++;
				var srcAttribute = m.Groups["srcAttr"].Value;
				string type = Regex.Match(srcAttribute, ":(?<type>.*?);base64,").Groups["type"].Value;
				string base64 = Regex.Match(srcAttribute, "base64,(?<base64>.*?)$").Groups["base64"].Value;

				if (string.IsNullOrEmpty(type) || string.IsNullOrEmpty(base64))
				{
					continue;
				}

				content = content.Replace(srcAttribute, "cid:" + imgCount);

				var tempResource = new LinkedResource(Base64ToImageStream(base64), new ContentType(type))
				{
					ContentId = imgCount.ToString(),
				};
				resourceCollection.Add(tempResource);
			}

			AlternateView alternateView = AlternateView.CreateAlternateViewFromString(content, null, MediaTypeNames.Text.Html);
			foreach (var item in resourceCollection)
			{
				alternateView.LinkedResources.Add(item);
			}

			return alternateView;
		}

		/// <summary>
		/// Get ses email config
		/// </summary>
		/// <param name="sesKey">Read config depend on sesKey</param>
		/// <returns></returns>
		private static SesEmailConfig GetEmailConfig(string sesKey)
		{
			var valideSmtpSSL = bool.TryParse(GetSesConfigByKey("SMTPSSL", sesKey), out var smtpSSL);
			var valideSmtpPort = int.TryParse(GetSesConfigByKey("SMTPPort", sesKey), out var smtpPort);

			return new SesEmailConfig
			{
				FromEmailAddress = GetSesConfigByKey("FromEmailAddress", sesKey),
				FromName = GetSesConfigByKey("FromName", sesKey),
				SMTPHost = GetSesConfigByKey("SMTPHost", sesKey),
				SMTPSSL = valideSmtpSSL && smtpSSL,
				SMTPPort = valideSmtpPort ? smtpPort : 25,
				Username = GetSesConfigByKey("Username", sesKey),
				Password = GetSesConfigByKey("Password", sesKey),
			};
		}

		/// <summary>
		/// Get value from web.config by key
		/// </summary>
		/// <param name="key"></param>
		/// <returns></returns>
		private static string GetSesConfigByKey(string key, string sesKey)
		{
			return ConfigurationManager.AppSettings[$"{sesKey}:{key}"] ?? string.Empty;
		}

		/// <summary>
		/// Ses email config class
		/// </summary>
		private sealed class SesEmailConfig
		{
			/// <summary>
			/// Email address send from
			/// </summary>
			public string FromEmailAddress { get; set; }

			/// <summary>
			/// Email name send from
			/// </summary>
			public string FromName { get; set; }

			/// <summary>
			/// Host Url
			/// </summary>
			public string SMTPHost { get; set; }

			/// <summary>
			/// Use or not SSL
			/// </summary>
			public bool SMTPSSL { get; set; }

			/// <summary>
			/// Port for SMTP
			/// </summary>
			public int SMTPPort { get; set; }

			/// <summary>
			/// User name for send email
			/// </summary>
			public string Username { get; set; }

			/// <summary>
			/// Password for send email
			/// </summary>
			public string Password { get; set; }
		}
	}
}
